import BaseChart from '../../BaseChart.js'

export default class VerticalTree extends BaseChart {
  constructor(id, data) {
    super(id, data);
  }

  init() {
    //初始化svg
    this.initSvg();
    //初始化主题内容部分
    this.initMainGroup();
    //初始化容器
    this.initTreeGroup();
    //拖拽
    this.initZoom();
    return this;
  }

  initTreeGroup() {
    this.treePathGroup = this.mg.append('g').attr('class', 'pathGroup');
    this.treeCircleGroup = this.mg.append('g').attr('class', 'circleGroup');
    this.treeTextGroup = this.mg.append('g').attr('class', 'textGroup');
  }
  initZoom() {
    this.svg.call(d3.zoom()
      .on('zoom', this.zoomed)
    )
  }

  render(data) {
    if (data) {
      this.data = data;
    }
    //更新数据
    this.renderData();
    //更新Path
    this.renderTreePath();
    //更新Circle
    this.renderTreeCircle();
    //更新Text
    this.renderTreeText();
    return this;
  }

  renderData() {
    //修改层次数据
    this.targetData = d3.hierarchy(this.data)
      .sum(d => d.value);
    //创建树模型生成器
    d3.tree()
      .size([this.innerWidth, this.innerHeight])
      .separation((a, b) => (a.parent == b.parent ? 1 : 2))(this.targetData);
  }

  renderTreePath() {
    this.treePathGroup
      .selectAll("path")
      .data(this.targetData.links(), d => d.target.data.id)
      .join('path')
      .transition()
      .attr("d", d3.linkVertical()
        .x(d => d.x)
        .y(d => d.y))
      .attr("fill", "none")
      .attr("stroke", "#999999")
      .attr("stroke-opacity", 0.8)
      .attr("stroke-width", '1.5px')
  }

  renderTreeCircle() {
    this.treeCircleGroup
      .selectAll("circle")
      .data(this.targetData.descendants(), d => d.data.id)
      .join(enter => enter
        .append('circle')
        .on('click', (d) => this.mouseclick(d))
        .attr('r', '5px')
        .attr('stroke', '#fff')
        .attr('stroke-width', '2.5px')
        .style('padding', '2.5px')
        .style("cursor", "pointer"),
        update => update,
        exit => exit.remove()
      )
      .transition()
      .attr("fill", d => d.data.children
        ? "red"
        : d.data._children
          ? "yellow"
          : "blue")
      .attr("transform", d => `translate(${d.x}, ${d.y})`)
  }

  renderTreeText() {
    this.treeTextGroup.selectAll("text")
      .data(this.targetData.descendants(), d => d.data.id)
      .join(enter => enter
        .append('text')
        .on('click', (d) => this.mouseclick(d))
        .style("cursor", "pointer")
        .style("fill", "#000")
        .style("font-size", "10px")
        .style("cursor", "pointer"),
        update => update,
        exit => exit.remove()
      )
      .transition()
      .attr("transform", d => `translate(${d.x}, ${d.y})`)
      .attr("x", d => d.x < Math.PI === !d.children ? 6 : -6)
      .text(d => d.data.name);
  }

  mouseclick = (e) => {
    let d = e.target.__data__;
    //如果要隐藏，则将子节点保存到一个临时属性中
    //如果要展开，则从临时属性中取值
    if (d.data._children) {
      d.data.children = d.data._children;
      d.data._children = null;
    } else {
      d.data._children = d.data.children;
      d.data.children = null;
    }
    //设置新的目标数据，数据一变动，则更新视图
    this.render()
  }

  // 伸缩函数
  zoomed = (event) => {
    this.mg.attr('transform', `translate(${event.transform.x},${event.transform.y}) scale(${event.transform.k})`)
  }
}